package com.tmt.config;

import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.swak.Constants;
import com.swak.config.customizer.SyncDataSourceOptionsCustomizer;
import com.swak.config.jdbc.database.DataSourceProperties;
import com.swak.config.jdbc.database.HikariDataSourceAutoConfiguration;
import com.swak.persistence.MS;
import com.swak.persistence.datasource.DataSourceHolder;
import com.swak.persistence.datasource.DynamicDataSource;
import com.swak.persistence.ms.MasterDataSource;
import com.swak.persistence.ms.SlaveDataSource;
import com.swak.persistence.mybatis.MasterSlaveInterceptor;
import com.swak.utils.Maps;

/**
 * 适合主从模式的多数据源配置
 * 
 * @author lifeng
 */
@Configuration
@ConditionalOnProperty(prefix = Constants.APPLICATION_PREFIX, name = "enableMasterSlaveDS", matchIfMissing = false)
public class MasterSlaveDSConfig {

	// ************ 定义主配置的资源配置 ****************
	@ConfigurationProperties(prefix = "spring.datasource.master")
	class MasterDataSourceProperties extends DataSourceProperties {

	}

	@ConfigurationProperties(prefix = "spring.datasource.slave")
	class SlaveDataSourceProperties extends DataSourceProperties {

	}

	@Bean
	@Primary
	public MasterDataSourceProperties primaryDataSourceProperties() {
		return new MasterDataSourceProperties();
	}

	@Bean
	public SlaveDataSourceProperties orderDataSourceProperties() {
		return new SlaveDataSourceProperties();
	}

	/**
	 * 配置主数据源
	 * 
	 * @param properties
	 * @return
	 */
	@Bean
	public DataSource masterDataSource(MasterDataSourceProperties properties,
			ObjectProvider<List<SyncDataSourceOptionsCustomizer>> customizersProvider) {
		MasterDataSource masterDataSource = new MasterDataSource();
		masterDataSource.addDataSource(
				new HikariDataSourceAutoConfiguration().hikariDataSource(properties, customizersProvider));
		return masterDataSource;
	}

	/**
	 * 配置从数据源
	 * 
	 * @param properties
	 * @return
	 */
	@Bean
	public DataSource slaveDataSource(SlaveDataSourceProperties properties,
			ObjectProvider<List<SyncDataSourceOptionsCustomizer>> customizersProvider) {
		SlaveDataSource slaveDataSource = new SlaveDataSource();
		slaveDataSource.addDataSource(
				new HikariDataSourceAutoConfiguration().hikariDataSource(properties, customizersProvider));
		return slaveDataSource;
	}

	@Bean
	@Primary
	public DataSource dynamicDataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
			@Qualifier("slaveDataSource") DataSource slaveDataSource) {

		// 配置多数据源
		Map<Object, Object> targetDataSources = Maps.newHashMap();
		targetDataSources.put(MS.Master, masterDataSource);
		targetDataSources.put(MS.Slave, slaveDataSource);

		// 配置动态数据源
		DataSource dynamicDataSource = new DynamicDataSource(masterDataSource, targetDataSources);
		DataSourceHolder.setDataSource(dynamicDataSource);
		return dynamicDataSource;
	}

	/**
	 * 配置主从拦截器
	 */
	@Bean
	public MasterSlaveInterceptor masterSlaveInterceptor() {
		return new MasterSlaveInterceptor();
	}
}